import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.FileWriter;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * This class is a collection of tools and utilities for the RocketAnalysisTool. This class
 * should not rely on persistence across method calls (i.e should not store any data). It is
 * purely a utility class designed to be used statically.
 */
public class RocketTools
{
	public static String writeHeader(String header, int size)
	{
		return writeHeader(header, "-", "|", size);
	}

	/**
	 * Wites the specified header text inside a box
	 * @param header
	 * @param size
	 */
	public static String writeHeader(String header, String hDel, String vDel, int size)
	{
		String dasher;
		StringBuffer buffer = new StringBuffer();
		buffer.append(vDel);
		for (int i = 0; i < size; i++)
		{
			buffer.append(hDel);
		}
		buffer.append(vDel);
		dasher = buffer.toString();
		buffer.append("\n");
		buffer.append(vDel);

		int headerSize = header.length() - 1;
		int lowerHalf = (size - headerSize) / 2;
		for (int i = 0; i < size; i++)
		{
			if (i < lowerHalf || i >= headerSize + lowerHalf)
				buffer.append(hDel);
			else if (i >= lowerHalf)
			{
				buffer.append(header);
				i += headerSize;
			}
		}

		dasher.replaceFirst("\n", "");
		buffer.append(vDel);
		buffer.append("\n");

		buffer.append(dasher);
		System.out.println(buffer.toString());
		return buffer.toString();
	}

	/**
	 * Method to read input from the keyboard
	 */
	public static String readInput()
	{
		BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
		String strInput = "";

		try
		{
			strInput = keyboard.readLine();
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}

		return strInput;
	}

	/**
	 * @param strDate
	 * @param dtStartDate
	 * @return
	 */
	public static Date processDate(String strDate)
	{
		Date dtStartDate = null;

		if (strDate.length() != 0)// checks if the date is entered or not
		{
			int year, month, day;
			try
			{
				day = Integer.parseInt(strDate.substring(0, 2));
				month = Integer.parseInt(strDate.substring(3, 5)) - 1;
				year = Integer.parseInt(strDate.substring(6, 10));

				if (day > 31 || month > 12)
				{
					System.err.println("Invalid date entered...current date will be added");
					dtStartDate = new Date();
				}
				else
				{
					Calendar calendar = Calendar.getInstance();
					calendar.set(year, month, day);

					Date currentDate = new Date();

					// Check if the date entered is a past date or not.
					if (currentDate.before(calendar.getTime()))
					{
						System.err.println("Start date must be either Today or a date in the past...current date will be added");
						dtStartDate = currentDate;
					}
					else
					{
						dtStartDate = calendar.getTime();
					}
				}
			}
			catch (StringIndexOutOfBoundsException s)
			{
				dtStartDate = new Date();
				System.err.println("Invalid start date entered...current date will be added...");
			}
			catch (NumberFormatException n)
			{
				dtStartDate = new Date();
				System.err.println("Invalid start date entered...current date will be added...");
			}
		}
		else
		{
			dtStartDate = new Date();
		}

		return dtStartDate;
	}

	public static LinkedList<String> extractJar(String sourceFile,
			LinkedList<String> sourceList)
	{
		try
		{
			System.out.println("sourceFile: " + sourceFile);
			JarFile jar = new JarFile(sourceFile);
			Enumeration enumer = jar.entries();
			File srcFile = new File(sourceFile);
			String path = srcFile.getParent();

			File tmpFolder = new File(path + File.separator + "tmp");
			tmpFolder.mkdir();
			tmpFolder.deleteOnExit();

			while (enumer.hasMoreElements())
			{
				JarEntry file = (JarEntry) enumer.nextElement();
				java.io.File f = new java.io.File(path + File.separator + "tmp"
						+ java.io.File.separator + file.getName());

				if (file.isDirectory())
				{ // if its a directory, create it
					f.mkdir();
					continue;
				}
				else if (f.getName().endsWith(".class"))
					sourceList.add(path + java.io.File.separator + "tmp"
							+ java.io.File.separator + file.getName());

				java.io.InputStream is = jar.getInputStream(file); // get the input stream
				java.io.FileOutputStream fos = new java.io.FileOutputStream(f);
				while (is.available() > 0)
				{ // write contents of 'is' to 'fos'
					fos.write(is.read());
				}
				fos.close();
				is.close();

			}
		}
		catch (IOException e1)
		{
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		return sourceList;
	}

	public static double promptAndWait(String msg)
	{
		double ret = -1;
		String str;
		while (ret == -1)
		{
			System.out.print(msg + ": ");

			try
			{
				str = RocketTools.readInput();
				ret = Integer.parseInt(str);
				return ret;
			}
			catch (NumberFormatException e)
			{
				System.out.println("Invalid input. Please enter a number.");
				ret = -1;
			}
		}
		return -1;
	}

	public static int promptBoundsCheckAndWait(String msg, int minimum, int maximum)
	{
		while (true)
		{
			System.out.print(msg + ": ");

			try
			{
				int input = Integer.parseInt(RocketTools.readInput());
				if (input >= minimum && input <= maximum) 
					return input;
				else
					System.out.println("Entered number is not in range.");
			}
			catch (NumberFormatException nfe)
			{
				System.out.println("Invalid input. Please enter a number.");
			}
		}
	}

	public static String[] promptParseAndWait(String msg)
	{
		String[] ret = null;
		String str = "";

		while (ret == null)
		{
			System.out.print(msg + ": ");

			try
			{
				str = RocketTools.readInput();
				ret = str.split(",");

				return ret;
			}
			catch (NumberFormatException e)
			{
				System.out.println("Invalid input. Please enter a number.");
				ret = null;
			}
		}
		return ret;
	}

	/**
	 * Creates a menu with the specified options and waits for the user to make a selection.
	 * @param options - The options to display in a menu.
	 * @return - The selected option.
	 */
	public static int createMenuAndWait(Object[] options)
	{
		int selection = 0;
		while (true)
		{
			for (int i = 0; i < options.length; i++)
				if (options[i] != null)
					System.out.println("[" + (i + 1) + "] " + options[i]);

			selection = (int) promptAndWait("Enter your selection");
			selection--;

			if (selection >= 0 && selection < options.length)
				break;
			else
				System.out.println("Invalid option entered. Please try again.");
		}
		return selection;
	}

	/**
	 * Method to wirte histogram data to a text file.
	 */
	public static void exportChartData(ChartVersion ch, String location) throws IOException
	{
		// Create the output histogram file
		FileWriter fileWriter = new FileWriter(location);
		fileWriter.write(RocketTools.writeHeader("Fan-Out Histogram Data", 42));
		fileWriter.write("\n\nVersion ID : " + ch.getVersion().getIdentifier() + "\n");
		fileWriter.write("=========================\n");

		// Obtain the Fan-out value for each version
		double fanOutValues[] = ch.getSeriesData();
		for (int a = 0; a < fanOutValues.length; a++)
		{
			fileWriter.write("\n\tFan-Out Value : " + fanOutValues[a] + "\n");
			fileWriter.write("\tFan-out Percentage : " + 100 * (a + 1) / fanOutValues.length
					+ "%\n");
		}

		fileWriter.close();
	}
}
